---
type: tutorial
title: 编写你的第一个浏览器脚本
description: >-
  教程：搭建你的 Astro 博客 -
  使用 Astro 脚本标签为移动导航添加客户端交互性
---
import Box from '~/components/tutorial/Box.astro';
import Checklist from '~/components/Checklist.astro';
import MultipleChoice from '~/components/tutorial/MultipleChoice.astro';
import Option from '~/components/tutorial/Option.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import { Steps } from '@astrojs/starlight/components';

让我们在移动屏幕上添加一个汉堡菜单（Hamburger Menus）以打开和关闭你的导航链接，这需要一些客户端的交互！

<PreCheck>
  - 创建一个汉堡菜单组件
  - 编写一个 `<script>` 使你的网站访问者可以打开和关闭导航菜单
  - 将你的 JavaScript 移动到 `.js` 文件中
</PreCheck>

## 搭建一个汉堡菜单组件

创建一个 `<Hamburger />` 组件，用于打开和关闭移动端菜单。

<Steps>
1. 在 `src/components/` 中创建一个名为 `Hamburger.astro` 的文件。

2. 将以下代码复制到你的组件中。这将表示你的三行「汉堡」菜单，在移动设备上打开和关闭导航链接菜单。（稍后你将把新的 CSS 样式添加到 `global.css` 中。）

    ```astro title="src/components/Hamburger.astro"
    --- 
    ---
    <div class="hamburger">
      <span class="line"></span>
      <span class="line"></span>
      <span class="line"></span>
    </div>
    ```

3. 将这个新的 `<Hamburger />` 组件放置在 `Header.astro` 的 `<Navigation />` 组件之前。

    <details>
    <summary>给我看看代码！</summary>

    ```astro title="src/components/Header.astro" ins={2,7}
    ---
    import Hamburger from './Hamburger.astro';
    import Navigation from './Navigation.astro';
    ---
    <header>
      <nav>
        <Hamburger />
        <Navigation />
      </nav>
    </header>
    ```
    </details>

4. 为你的 Hamburger 组件添加以下样式：

    ```css title="src/styles/global.css" ins={2-13, 56-58}
    /* 导航样式 */
    .hamburger {
      padding-right: 20px;
      cursor: pointer;
    }

    .hamburger .line {
      display: block;
      width: 40px;
      height: 5px;
      margin-bottom: 10px;
      background-color: #ff9776;
    }

    .nav-links {
      width: 100%;
      top: 5rem;
      left: 48px;
      background-color: #ff9776;
      display: none;
      margin: 0;
    }

    .nav-links a {
      display: block;
      text-align: center;
      padding: 10px 0;
      text-decoration: none;
      font-size: 1.2rem;
      font-weight: bold;
      text-transform: uppercase;
    }

    .nav-links a:hover, a:focus {
      background-color: #ff9776;
    }

    .expanded {
      display: unset;
    }

    @media screen and (min-width: 636px) {
      .nav-links {
        margin-left: 5em;
        display: block;
        position: static;
        width: auto;
        background: none;
      }

      .nav-links a {
        display: inline-block;
        padding: 15px 20px;
      }

      .hamburger {
        display: none;
      }
    }
    ```
</Steps>

## 编写你的第一个 script 标签

你的页眉还不具有**交互性**，因为它无法响应用户输入，比如点击汉堡菜单来显示或隐藏导航链接菜单。

添加一个 `<script>` 标签提供客户端 JavaScript，以「监听」用户事件并做出相应的响应。

<Steps>
1. 将以下 `<script>` 标签添加到 `index.astro`，就在结束的 `</body>` 标签之前。

    ```astro title="src/pages/index.astro" ins={2-6}
      <Footer />
      <script>
        document.querySelector('.hamburger').addEventListener('click', () => {
          document.querySelector('.nav-links').classList.toggle('expanded');
        });
      </script>
    </body>
    ```

2. 再次在各种尺寸下检查你的浏览器预览，并验证你是否在这个页面上拥有一个能够根据屏幕尺寸响应并对用户输入作出响应的正常运作的汉堡菜单。
</Steps>

### 导入一个 `.js` 文件

你可以将你的 JavaScript 直接写在每个页面上，也可以将你的 `<script>` 标签的内容移动到项目中自己的 `.js` 文件中。

<Steps>
1. 创建 `src/scripts/menu.js`（你将不得不创建一个新的 `/scripts/` 文件夹），并将你的 JavaScript 移动到其中。

    ```js title="src/scripts/menu.js"
    document.querySelector('.hamburger').addEventListener('click', () => {
      document.querySelector('.nav-links').classList.toggle('expanded');
    });
    ```

2. 用以下文件导入替换 `index.astro` 中的 `<script>` 标签的内容：

    ```astro title="src/pages/index.astro" ins={7} del={3-5}
      <Footer />
      <script>
        document.querySelector('.hamburger').addEventListener('click', () => {
          document.querySelector('.nav-links').classList.toggle('expanded');
        });

        import "../scripts/menu.js";
      </script>
    </body>
    ```

3. 再次在较小的尺寸下检查你的浏览器预览，验证汉堡菜单是否仍然可以打开和关闭导航链接菜单。

4. 在你的其他两个页面 `about.astro` 和 `blog.astro` 中添加相同的带有导入的 `<script>`，并验证每个页面上是否有一个响应式、交互式的页眉。

     ```astro title="src/pages/about.astro & src/pages/blog.astro" ins={2-4}
      <Footer />
      <script>
        import "../scripts/menu.js";
      </script>
    </body>
    ```
</Steps>

:::note[要点]
你之前使用了一些 JavaScript 来构建你网站的部分内容：

- 动态定义页面标题和标题
- 在关于页面上映射技能列表
- 有条件地显示 HTML 元素

这些命令都在构建时执行，为你的网站创建静态 HTML，然后代码被「丢弃」。

**`<script>` 标签中的 JavaScript 被发送到浏览器**，并可根据用户的交互（如刷新页面或切换输入）运行。
:::

<Box icon="question-mark">

### 测试你的知识

1. Astro 何时运行在组件的前置数据中编写的任何 JavaScript？
    <MultipleChoice>
      <Option>
        Astro 从不运行 JavaScript
      </Option>
      <Option isCorrect>
        在编译（Build）时
      </Option>
      <Option>
        当访问者点击按钮时
      </Option>
    </MultipleChoice>

2. 可选地，Astro 可以发送 JavaScript 到浏览器以实现：
    <MultipleChoice>
      <Option>
        用户点击页面链接
      </Option>
      <Option>
        更快的加载时间
      </Option>
      <Option isCorrect>
        客户端交互
      </Option>
    </MultipleChoice>

3. 当编写或导入到组件的 `<script>` 标签中时，客户端 JavaScript 将被发送到用户的浏览器中：
    <MultipleChoice>
      <Option isCorrect>
        在 `<script>` 标签中
      </Option>
      <Option>
        在 `.astro` 文件的代码块内
      </Option>
      <Option>
        在 `global.css` 中
      </Option>
    </MultipleChoice>

</Box>

<Box icon="check-list">

## 任务清单

<Checklist>
- [ ] 我可以使用 `<script>` 标签在客户端添加交互性的 JavaScript。
- [ ] 我可以将 `.js` 文件导入到 `<script>` 标签中。
</Checklist>

</Box>

### 相关资源

[Astro 中的客户端脚本](/zh-cn/guides/client-side-scripts/)
